import { app, BrowserWindow, ipcMain } from 'electron';
import { logger } from './logger';

// Store for captured errors
interface ErrorRecord {
  id: string;
  timestamp: number;
  type: string;
  message: string;
  stack?: string;
  info?: any;
  source: 'main' | 'node' | 'renderer' | 'automation';
}

class ErrorHandler {
  private mainWindow: BrowserWindow | null = null;
  private errorQueue: ErrorRecord[] = [];
  private isReady = false;

  constructor() {
    // Set up Node.js global error handlers
    this.setupGlobalHandlers();
  }

  // Initialize with the main window reference
  public initialize(mainWindow: BrowserWindow) {
    this.mainWindow = mainWindow;
    this.isReady = true;

    // Send any queued errors
    if (this.errorQueue.length > 0) {
      this.flushErrorQueue();
    }
  }

  // Set up global error handlers for Node.js process
  private setupGlobalHandlers() {
    // Handle uncaught exceptions
    process.on('uncaughtException', (error: Error) => {
      this.captureError({
        type: 'uncaughtException',
        message: error.message,
        stack: error.stack,
        source: 'main'
      });
      logger.error(`Uncaught Exception: ${error.message}`, { stack: error.stack });
    });

    // Handle unhandled promise rejections
    process.on('unhandledRejection', (reason: any, promise: Promise<any>) => {
      const message = reason instanceof Error ? reason.message : String(reason);
      const stack = reason instanceof Error ? reason.stack : undefined;

      this.captureError({
        type: 'unhandledRejection',
        message,
        stack,
        source: 'main'
      });
      logger.error(`Unhandled Rejection: ${message}`, { stack });
    });

    // Listen for errors from renderer process
    ipcMain.on('error:report', (event, errorData) => {
      this.captureError({
        ...errorData,
        source: errorData.source || 'renderer'
      });
    });

    // API to get all errors
    ipcMain.handle('error:getAll', () => {
      return this.errorQueue;
    });

    // API to clear errors
    ipcMain.handle('error:clear', () => {
      this.errorQueue = [];
      return true;
    });
  }

  // Capture an error and send to renderer if window is available
  public captureError(error: Omit<ErrorRecord, 'id' | 'timestamp'>) {
    const errorRecord: ErrorRecord = {
      id: Date.now().toString(36) + Math.random().toString(36).substring(2),
      timestamp: Date.now(),
      ...error
    };

    // Log the error
    logger.error(`[${errorRecord.source}] ${errorRecord.type}: ${errorRecord.message}`, {
      stack: errorRecord.stack,
      info: errorRecord.info
    });

    // Add to the queue
    this.errorQueue.push(errorRecord);

    // Keep queue limited to most recent 100 errors
    if (this.errorQueue.length > 100) {
      this.errorQueue.shift();
    }

    // Forward to window if ready
    this.forwardErrorToRenderer(errorRecord);
  }

  // Send error to renderer process
  private forwardErrorToRenderer(error: ErrorRecord) {
    if (this.isReady && this.mainWindow && !this.mainWindow.isDestroyed()) {
      this.mainWindow.webContents.send('error:new', error);
    }
  }

  // Flush any queued errors to the renderer
  private flushErrorQueue() {
    if (this.isReady && this.mainWindow && !this.mainWindow.isDestroyed()) {
      this.errorQueue.forEach(error => {
        this.mainWindow?.webContents.send('error:new', error);
      });
    }
  }
}

// Create a singleton instance
export const errorHandler = new ErrorHandler();
